﻿using Jinjia.Approve.Common.Enum;
using Jinjia.Approve.Entity.Entity.JJFlow;
using Jinjia.Approve.IRepository;
using Jinjia.Approve.IRepository.JJFlow;
using Jinjia.Approve.IService;
using Jinjia.Approve.IService.JJFlow;
using Jinjia.Approve.IService.JJFlow.Action;
using Jinjia.Approve.IService.JJFlow.BPM;
using Jinjia.Approve.Model.Enum;
using Jinjia.Approve.Model.Input.JJFlow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Jinjia.Approve.Common.Extensions;
using JinJia.Core.Base.Exceptions;
using Jinjia.Approve.Model.VM.JJFlow.DTO;
using Jinjia.Approve.Entity;
using Jinjia.Approve.Model.VM.JJFlow;
using Jinjia.Core.Transaction.Service;
using Jinjia.Core.UnitOfWork.UnitOfWorkComponent;

namespace Jinjia.Approve.Service.JJFlow.Action
{
    public class JJFlowActionPassOn : IJJFlowActionPassOn
    {
        private readonly IJJFlowNodeService _jJFlowNodeService;
        private readonly IJJFlowBpmXMLParserService _jjFlowBpmXMLParserService;
        private readonly IJJFlowCommentService _jjFlowCommentService;
        private readonly IErpaUserRepository _erpaUserRepository;
        private readonly IFlowInstanceEmpRepository _flowInstanceEmpRepository;
        private readonly IFlowNodeEmpRepository _flowNodeEmpRepository;
        private readonly IFlowDesignRepository _flowDesignRepository;
        private readonly IFlowTrackRepository _flowTrackRepository;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IFlowInstanceEmpBakRepository _flowInstanceEmpBakRepository;
        private readonly ITransactionCAP _transactionCap;

        public JJFlowActionPassOn(IJJFlowNodeService jJFlowNodeService,
            IJJFlowBpmXMLParserService jjFlowBpmXMLParserService,
            IJJFlowCommentService jJFlowCommentService,
            IErpaUserRepository erpaUserRepository,
            IFlowInstanceEmpRepository flowInstanceEmpRepository,
            IFlowNodeEmpRepository flowNodeEmpRepository,
            IFlowDesignRepository flowDesignRepository,
            IFlowTrackRepository flowTrackRepository,
            IUnitOfWork unitOfWork,
            IFlowInstanceEmpBakRepository flowInstanceEmpBakRepository,
            IDistributedTransactionService distributedTransactionService)
        {
            _jJFlowNodeService = jJFlowNodeService;
            _jjFlowBpmXMLParserService = jjFlowBpmXMLParserService;
            _jjFlowCommentService = jJFlowCommentService;
            _erpaUserRepository = erpaUserRepository;
            _flowInstanceEmpRepository = flowInstanceEmpRepository;
            _flowNodeEmpRepository = flowNodeEmpRepository;
            _flowDesignRepository = flowDesignRepository;
            _flowTrackRepository = flowTrackRepository;
            _unitOfWork = unitOfWork;
            _flowInstanceEmpBakRepository = flowInstanceEmpBakRepository;
            _transactionCap = distributedTransactionService.CreateCAP();
        }

        public async Task PassOn(PassOnRequest request, int instanceId, int userId)
        {
            #region 获取操作人信息

            var handoverUser = await _erpaUserRepository.GetById(request.HandoverUserId);
            if (handoverUser == null || handoverUser.id == 0)
            {
                throw new BusinessException("交接人不存在！");
            }
            var operatorUserId = instanceId > 0 ? userId : request.OperatorUserId;
            var operatorUser = await _erpaUserRepository.GetById(operatorUserId);
            if (operatorUser == null || operatorUser.id == 0)
            {
                throw new BusinessException("操作人不存在！");
            }
            if (handoverUser.id == operatorUser.id)
            {
                return;
            }

            #endregion

            #region 审批转交

            var empList = await _flowInstanceEmpRepository.GetApprovalPendingList(operatorUser.id, new List<int> { instanceId }, null);

            if (empList != null && empList.Count > 0)
            {
                List<int> idList = await this.ExecTransferFlowsAsync(empList, handoverUser, operatorUser, 0);

                //更新模板
                if (instanceId <= 0 && idList.Count > 0)
                {
                    //更新审批人
                    await _flowNodeEmpRepository.ChangeApprover(handoverUser.id, operatorUser.id);
                    //更新BPM Xml
                    var templateIdList = empList.Where(m => idList.Contains(m.id)).Select(m => m.template_id).Distinct().ToList();
                    foreach (var templateId in templateIdList)
                    {
                        var designModel = await _flowDesignRepository.GetByTemplateId(templateId);
                        if (designModel == null || designModel.id == 0)
                        {
                            continue;
                        }
                        var bpmnXml = _jjFlowBpmXMLParserService.BPMReplaceUserIdList(designModel.design_xml, handoverUser.id.ToString(), operatorUser.id.ToString());
                        if (bpmnXml != null)
                        {
                            designModel.design_xml = bpmnXml.OuterXml;
                            designModel.update_user_id = -1;
                            designModel.update_time = DateTime.Now;
                            await _flowDesignRepository.UpdateAsync(designModel);
                        }
                    }
                }
            }

            #endregion
        }

        public async Task<bool> TransferFlowsAsync(List<int> instanceEmpIds, int handoverUserId, int loginUserId)
        {
            // 过滤id为0的无意义id, 当审批状态为已通过 前端会传0
            instanceEmpIds = instanceEmpIds.FindAll(x => x != 0);
            if (instanceEmpIds.Count == 0)
            {
                return true;
            }

            var handoverUser = await _erpaUserRepository.GetById(handoverUserId);

            if (handoverUser is null)
            {
                throw new BusinessException("交接人不存在！");
            }

            if (handoverUser.action_flag == 0)
            {
                throw new BusinessException("交接人状态不可用！");
            }

            var empList = await _flowInstanceEmpRepository.GetApprovalPendingList(0, null, instanceEmpIds);

            this._unitOfWork.BeginTran();

            _ = await this.ExecTransferFlowsAsync(empList, handoverUser, null, loginUserId);

            this._unitOfWork.CommitTran();

            return true;
        }


        /// <summary>
        /// 转交
        /// </summary>
        /// <param name="empList">转交审批列表</param>
        /// <param name="handoverUser">交接人</param>
        /// <param name="operatorUser">操作人</param>
        /// <param name="loginUserId">当前登录id</param>
        /// <returns></returns>
        private async Task<List<int>> ExecTransferFlowsAsync(List<InstanceEmpDTO> empList, erpa_user_tbl handoverUser, erpa_user_tbl operatorUser, int loginUserId)
        {
            List<jj_flow_track> resultList = new List<jj_flow_track>();
            List<int> idList = new List<int>();

            if (empList.Count() == 0)
            {
                return idList;
            }

            var nodeIds = empList.Select(m => m.node_id).Distinct().ToList();
            var nodeList = await _jJFlowNodeService.GetNodeByIds(nodeIds);//包含已删除的节点

            List<int> userIds = empList.Select(o => o.user_id).Distinct().ToList();
            var oldUserDatas = await _erpaUserRepository.GetListAsync(o => userIds.Contains(o.id));

            foreach (var item in empList)
            {
                var nodeModel = nodeList?.SingleOrDefault(m => m.id == item.node_id);

                if (nodeModel == null)
                {
                    continue;
                }

                var nodeEmpList = await _flowInstanceEmpRepository.GetList(item.instance_id, item.node_id);

                //判断节点是否已经审批通过
                switch (nodeModel.emp_type)
                {
                    case (int)JJFlowNodeEmpTypeEnum.OrNode:
                        if (nodeEmpList.Any(m => m.is_complete == 1))
                        {
                            continue;
                        }
                        break;

                    case (int)JJFlowNodeEmpTypeEnum.AndNode:
                        if (!nodeEmpList.Any(m => m.is_complete == 0))
                        {
                            continue;
                        }
                        break;

                    default:
                        continue;
                }

                var currentNode = await _jJFlowNodeService.GetNodeById(item.current_node_id);//包含已删除的节点

                if (currentNode != null && currentNode.id > 0)
                {
                    resultList.Add(new jj_flow_track
                    {
                        instance_id = item.instance_id,
                        operation_result = nodeModel.node_type,
                        node_id = currentNode.id,
                        node_name = nodeModel.node_name,
                        action_type = (int)EnumDb.JJFlowOperationTypeEnum.Approve,
                        action_type_name = $"将{oldUserDatas.FirstOrDefault(o => o.id == item.user_id)?.user_name}转交给{handoverUser.user_name}",
                        from_emp = operatorUser != null ? operatorUser.id.ToString() : item.user_id.ToString(),
                        update_user_id = operatorUser != null ? operatorUser.id : loginUserId,
                        create_user_id = operatorUser != null ? operatorUser.id : loginUserId
                    });

                    idList.Add(item.id);
                }
            }

            //插入历史记录
            if (resultList.Any())
            {
                await _flowTrackRepository.InsertAsync(resultList);
            }

            //写入评论表
            foreach (var item in resultList)
            {
                await _jjFlowCommentService.SaveComment(item);
            }

            //处理转交
            if (idList.Any())
            {
                // 转交流程集合
                var transferEmps = empList.FindAll(x => idList.Contains(x.id));

                // 删除被转交的流程
                _ = await _flowInstanceEmpRepository.DeleteAsync(x => idList.Contains(x.id));

                // 写入备份表
                _ = await _flowInstanceEmpBakRepository.InsertAsync(transferEmps.MapTo<jj_flow_instance_emp_bak>());

                // 构建新流程
                transferEmps.ForEach(item =>
                {
                    item.user_id = handoverUser.id;
                    item.source_emp_id = item.id;
                    item.id = 0;
                });

                // 写入新流程
                await _flowInstanceEmpRepository.Save(transferEmps.MapTo<jj_flow_instance_emp>());

                // 发布审批流操作消息
                transferEmps.GroupBy(x => new JJFlowOperate
                    {
                        InstanceId = x.instance_id,
                        TransferEmpId = x.source_emp_id
                    })
                    .ForEach(jjFlowOperateGroup => _transactionCap.Publish(jjFlowOperateGroup.Key));
            }

            return idList;
        }
    }
}